# coding=utf-8

import socket
import threading
import time
import traceback
from concurrent.futures import wait


class BaseRequestHandler(threading.Thread):
    server = None
    request = None
    client_address = None

    task = None
    pool = None

    def __init__(self, server, request, client_address):
        super(BaseRequestHandler, self).__init__()
        self.server = server
        self.request = request
        self.client_address = client_address
        self.pool = server.proxy_app.threads

    def start(self):
        self.task = self.pool.submit(lambda x: x.run(), self)

    def join(self):
        if self.task.done():
            return
        wait([self.task])

    def run(self):
        try:
            self.handle()
        finally:
            self.teardown(True)
            self.server.close_handler(self)

    def setup(self, as_active):
        pass

    def teardown(self, as_active):
        pass

    def handle(self):
        print(self.request, self.client_address)
        conn = self.request
        conn.sendall('欢迎致电 10086，请输入1xxx,0转人工服务.'.encode('gbk'))
        flag = True
        while flag:
            data = conn.recv(1024)
            if data == 'exit':
                flag = False
            elif data == '0':
                conn.sendall('通过可能会被录音.balabala一大推'.encode('gbk'))
            else:
                conn.sendall('请重新输入.'.encode('gbk'))

    def shutdown(self, as_active):
        if self.request:
            try:
                self.request.shutdown(2)
            except Exception:
                pass
            try:
                self.request.close()
            except Exception:
                pass
            self.request = None

    def write(self, data):
        self.request.write(data)


class FrontServer:
    socket = None
    thread = None
    active_client = None
    lock = threading.Lock()
    proxy_app = None

    task = None

    def __init__(self, proxy, host_port, RequestHandlerClass):
        super(FrontServer, self).__init__()
        self.proxy_app = proxy
        self.RequestHandlerClass = RequestHandlerClass

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind(host_port)
        self.socket.listen(5)

    def shutdown(self):
        try:
            self.socket.shutdown(2)
        except socket.error as e:
            print("socket error")
        finally:
            pass
        try:
            self.socket.close()
        except socket.error as e:
            print("socket error")
        finally:
            pass
        self.join()
        try:
            if self.active_client:
                self.active_client.shutdown(True)
                self.active_client.join()
        except Exception:
            traceback.print_exc()

    def run(self):
        try:
            while True:
                request, client_address = self.socket.accept()
                client = self.RequestHandlerClass(self, request, client_address)
                as_active = False
                self.lock.acquire()
                if self.active_client is None:
                    as_active = True
                    self.active_client = client
                self.lock.release()
                try:
                    client.setup(as_active)
                except Exception:
                    pass
                if as_active:
                    client.start()
                else:
                    client.teardown(as_active)
        except Exception:
            traceback.print_exc()
            pass

    def close_handler(self, hdl):
        # self.lock.acquire()
        self.active_client = None
        # self.lock.release()

    def write(self, data):
        # self.lock.acquire()
        if self.active_client:
            self.active_client.write(data)
        # self.lock.release()

    def start(self):
        self.task = self.proxy_app.threads.submit(lambda x: x.run(), self)

    def join(self):
        if self.task.done():
            return
        wait([self.task])


if __name__ == '__main__':
    s = FrontServer(('127.0.0.1', 11211), BaseRequestHandler)
    # FrontServer.run(s)
    # s.serve_forever()
    s.start()
    time.sleep(10)
    s.shutdown()
    print("all end")


